/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "Window.h"
#include "MBT_Engine.h"

#include "core/时间.h"


#include <场景/场景.h>
#include <系统/系统平台.h>
#include "底层绘图/intern/绘图框架.h"
#include "底层绘图/intern/Vulkan/Vulkan框架.h"

#include <SDL3/SDL.h>
#include <SDL3/SDL_vulkan.h>
#include <SDL3/SDL_gpu.h>
#include <vulkan/vulkan.h>




#include <map>
#include <imm.h>
#include <time.h>
using namespace std;

#include "resource.h"


#pragma comment(lib, "imm32.lib")
#pragma comment(lib, "gdi32.lib")

#ifdef _DEBUG

//#define SDL3_LIB "D:/U/DEV/SDL3/lib/SDL3-static_d.lib"

#else

//#define SDL3_LIB "D:/U/DEV/SDL3/lib/SDL3-static.lib"

#endif // DEBUG

//#pragma comment(lib, SDL3_LIB)
#pragma comment(lib, "D:/U/DEV/SDL3/lib/SDL3.lib")






//int f_异步事件(void *userdata, SDL_Event * event);
LRESULT CALLBACK Windows窗口回调(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

#define IDM_EXIT				105
#define IDC_PROJECT1			109

#define VK_LSHIFT 0xA0 
#define VK_RSHIFT 0xA1 
#define VK_LCONTROL 0xA2 


static HINSTANCE m_hInstance = 0;
static uint32 f = 0;

std::u16string f_win32_get输入法完成文本(HIMC hImc);


bool f_window_set鼠标样式(E_鼠标样式 样式) {
	HCURSOR s;
	switch (样式) {
		//case E_鼠标样式::e_鼠标样式_默认:		s = LoadCursor(NULL, IDC_ARROW);	break;
		//case E_鼠标样式::e_鼠标样式_默认:		return false;
		case E_鼠标样式::e_鼠标样式_横向双箭头: s = LoadCursor(NULL, IDC_SIZEWE); break;
		case E_鼠标样式::e_鼠标样式_纵向双箭头: s = LoadCursor(NULL, IDC_SIZENS); break;
		case E_鼠标样式::e_鼠标样式_等待:       s = LoadCursor(NULL, IDC_WAIT);   break;

		default:
			return false;
	}

	SetCursor(s);
	return true;
}

LPCWSTR stringToLPCWSTR(std::string orig) {
	size_t origsize = orig.length() + 1;
	const size_t newsize = 100;
	size_t convertedChars = 0;
	wchar_t *wcstring = (wchar_t *)malloc(sizeof(wchar_t)*(orig.length() - 1));
	mbstowcs_s(&convertedChars, wcstring, origsize, orig.c_str(), _TRUNCATE);

	return wcstring;
}

inline HINSTANCE GetCurrentModule(string path="") {
	if (path.empty()) {
		return GetModuleHandle(0);
	}
	//return GetModuleHandle(path.c_str());
	return GetModuleHandle(stringToLPCWSTR(path));
}


// 任意时刻都能强制前台
static void f_MakeForeground(HWND hWnd) {
	HWND hFore = GetForegroundWindow();
	if (hWnd == hFore) return;   // 已在最前

	DWORD foreThread = GetWindowThreadProcessId(hFore, nullptr);
	DWORD myThread   = GetCurrentThreadId();

	AttachThreadInput(myThread, foreThread, TRUE);
	SwitchToThisWindow(hWnd, TRUE);
	//AttachThreadInput(myThread, foreThread, FALSE);
}

static void f_win32_set输入法面板位置(HIMC hImc) {
	CANDIDATEFORM cand;
	cand.dwIndex = 0;
	cand.dwStyle = CFS_CANDIDATEPOS;
	POINT p;
	GetCursorPos(&p);

	p.x = GetSystemMetrics(SM_CXSIZE);
	p.y = GetSystemMetrics(SM_CYSIZE);

	auto 光标位置 = f_widget_get输入法窗口位置();
	cand.ptCurrentPos.x = 光标位置.x + p.x;
	cand.ptCurrentPos.y = 光标位置.y + p.y;
	ImmSetCandidateWindow(hImc, &cand);

}



std::u16string f_win32_get输入法完成文本(HIMC hImc) {
	DWORD dwSize = ImmGetCompositionStringW(hImc, GCS_RESULTSTR, NULL, 0);
	dwSize += sizeof(WCHAR);
	LPCWSTR lpcwString = (LPCWSTR)GlobalAlloc(GPTR, dwSize);
	ImmGetCompositionStringW(hImc, GCS_RESULTSTR, (LPVOID)lpcwString, dwSize);
	//auto lpcwInput = (LPCWSTR)GlobalAlloc(GPTR, dwSize);
	//memcpy((void*)lpcwInput, lpcwString, dwSize);

	auto iSize = WideCharToMultiByte(936, 0, lpcwString, -1, NULL, 0, NULL, NULL);
	std::wstring 文本;
	文本.resize(iSize);
	WideCharToMultiByte(936, 0, lpcwString, -1, (LPSTR)(文本.data()), iSize, NULL, NULL);

	文本 = lpcwString;
	return f_str_wstring_to_u16(文本);
}

static std::u16string f_win32_get输入法输入字符(HIMC hImc) {
	DWORD dwSize = ImmGetCompositionStringW(hImc, GCS_COMPSTR, NULL, 0);
	dwSize += sizeof(WCHAR);
	LPCWSTR lpcwString = (LPCWSTR)GlobalAlloc(GPTR, dwSize);
	ImmGetCompositionStringW(hImc, GCS_COMPSTR, (LPVOID)lpcwString, dwSize);
	//auto lpcwInput = (LPCWSTR)GlobalAlloc(GPTR, dwSize);
	//memcpy((void*)lpcwInput, lpcwString, dwSize);

	auto iSize = WideCharToMultiByte(936, 0, lpcwString, -1, NULL, 0, NULL, NULL);
	std::wstring 文本;
	文本.resize(iSize);
	WideCharToMultiByte(936, 0, lpcwString, -1, (LPSTR)(文本.data()), iSize, NULL, NULL);

	文本 = lpcwString;
	return f_str_wstring_to_u16(文本);
}




struct S_sdl_window {
	DEF_VK_窗口交换面

	SDL_Window* m_window;
	SDL_Renderer* m_renderer;
	SDL_PropertiesID props;
};

S_Window::S_Window(S_设备环境& Ctx) : C_Widget() {
	m_Type = E_WidgetType::t_窗口;
	m_TypeName = "窗口";
	m_弹出窗口 = false;

	m_处理输入事件 = true;

	m_绘图环境 = nullptr;
	m_绘图框架 = nullptr;
	m_窗口GM = nullptr;
	m_Window = nullptr;
	m_采样 = E_MS次数::e_MS_4;
	m_帧数 = 0;


	m_sdl_window = new S_sdl_window;
	m_sdl_window->m_window = nullptr;
	m_sdl_window->m_renderer = nullptr;
	m_sdl_window->m_vk_surface = {};

	m_是否有焦点 = true;
	m_Input = f_input_create输入设备();


	if (!m_hInstance) {
		m_hInstance = GetCurrentModule();

		WNDCLASS wc;

		wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;  
		wc.lpfnWndProc = Windows窗口回调;
		wc.cbClsExtra = 0;
		wc.cbWndExtra = 0;
		wc.hInstance = m_hInstance;
		wc.hIcon = LoadIcon(m_hInstance, MAKEINTRESOURCE(IDI_ICON2));
		wc.hCursor = LoadCursor(0, IDC_ARROW);
		wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
		wc.lpszMenuName = 0;
		wc.lpszClassName = L"只眼";

		if (!RegisterClass(&wc)) {
			MessageBox(0, L"RegisterClass Failed.", 0, 0);
			return;
		}

		S_引擎配置::g_系统目录.resize(128);
		GetWindowsDirectory(S_引擎配置::g_系统目录.data(), 512);
		

		//ChangeWindowMessageFilter(WM_INPUTLANGCHANGEREQUEST, MSGFLT_ADD);
		//ChangeWindowMessageFilter(WM_INPUTLANGCHANGE, MSGFLT_ADD);
	}

	m_时间start = 0;
	m_时间end = clock();
}

S_Window::~S_Window() {
	if (m_sdl_window->m_window) {
		SDL_DestroyWindow(m_sdl_window->m_window);
		SDL_DestroyRenderer(m_sdl_window->m_renderer);
	}
	delete m_sdl_window;


	f_df_release_win32Surface(m_UIctx->m_Ctx, m_窗口GM->m_渲染面);
	

	if (m_Input->m_鼠标设备) {
		f_input_release输入设备(m_Input);
	}
	
	f_release组件管理(m_窗口GM);
	m_窗口GM = 0;

	PostQuitMessage(0);
	CloseWindow((HWND)m_窗口钩柄);
	DestroyWindow((HWND)m_窗口钩柄);
	
	delete m_UIctx;
	m_UIctx = nullptr;

	S_Engine::g_窗口容器.erase((uint64)m_窗口钩柄);

}


// 钩子句柄
HHOOK g_shellHook;



uint64 S_Window::f_创建窗口(string 标题, int32 x, int32 y, int32 w, int32 h, bool 显示, string path) {
	m_Size.x = w;
	m_Size.y = h;
	m_绘制 = true;

	std::wstring mMainWndCaption = L"只眼";
	RECT R = { 0, 0, w, h };
	AdjustWindowRect(&R, WS_OVERLAPPEDWINDOW, false);
	int width = R.right - R.left;
	int height = R.bottom - R.top;


	auto hwnd = CreateWindowExW(0, mMainWndCaption.c_str(), L"窗口", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width, height, 0, 0, m_hInstance, 0);
	if (!m_hInstance) {
		MessageBox(0, L"CreateWindow Failed.", 0, 0);
		return 0;
	}
	m_窗口钩柄 = (S_结构指针)hwnd;

	ShowWindow((HWND)m_窗口钩柄, 显示 ? SW_SHOW : SW_HIDE);
	UpdateWindow((HWND)m_窗口钩柄);
	DragAcceptFiles((HWND)m_窗口钩柄, true);
	SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);


	f_initInput(m_Input, m_窗口钩柄, (S_结构指针)m_hInstance);
	S_Engine::g_窗口容器[(uint64)m_窗口钩柄] = this;

	HIMC hImc = ImmGetContext(hwnd);
	ImmReleaseContext(hwnd, hImc);

	return 0;
}

void S_Window::f_窗口重置() {
	int32 w, h;
}


void ForceSyncInput(HWND hWnd) {
	

	// 1. 取前台线程的当前 HKL
	HKL hkl = GetKeyboardLayout(
		GetWindowThreadProcessId(GetForegroundWindow(), nullptr));

	// 2. 激活到本线程
	ActivateKeyboardLayout(hkl, 0);

	// 3. 零像素布局变化，强制系统刷新
	SetWindowPos(hWnd, nullptr, 0, 0, 0, 0,
				 SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
}

SDL_Event sdl_event;
bool S_Window::f_轮询窗口事件(bool& 累计渲染) {
	if (!m_显示) return false;
	
	/*if (m_sdl_window->m_window) {
		auto event = SDL_PollEvent(&sdl_event);

		if (event) {
			auto id = SDL_GetWindowID(m_sdl_window->m_window);

			if ((sdl_event.type == SDL_EVENT_QUIT || sdl_event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED) && id == sdl_event.window.windowID) {
				SDL_HideWindow(m_sdl_window->m_window);
				m_可视 = false;
				return false;
			}
			
			switch (sdl_event.type) {
				case SDL_EVENT_WINDOW_RESIZED: {
					int32 w, h;
					SDL_GetWindowSize(m_sdl_window->m_window, &w, &h);
					m_Size = _Vec2(w, h);
					std::cout << "修改窗口大小" << std::endl;
					break;
				}
				default:
					break;
			}
		}
		
		

		f_widget_执行待添加部件();
		f_ui_动态销毁UI部件(m_窗口GM);

		ivec2 m_ViewSize = { (int32)m_Size.x, (int32)m_Size.y };
		f_ui_绘制组件(m_窗口GM);
		f_ui_更新UI部件属性(m_窗口GM, m_ViewSize);

		//f_Draw_Begin_帧缓存(&m_窗口GM->m_UICtx->m_Ctx, m_ui_sruface->m_帧缓存, 0);
		//f_ui_绘制到屏幕(m_窗口GM, m_ViewSize);
		//f_Draw_end_帧缓存(&m_窗口GM->m_UICtx->m_Ctx);


		// 清除屏幕
		SDL_SetRenderDrawColor(m_sdl_window->m_renderer, 0, 0, 0, 255);
		SDL_RenderClear(m_sdl_window->m_renderer);

		// 使用 SDL3 的 UI 组件绘制
		SDL_FRect rect = {100, 100, 200, 100};
		SDL_SetRenderDrawColor(m_sdl_window->m_renderer, 0, 255, 0, 255);
		SDL_RenderFillRect(m_sdl_window->m_renderer, &rect);

		SDL_Rect destRect = {0, 0, 0, 0};
		SDL_RenderTexture(m_sdl_window->m_renderer, 0, nullptr, 0);


		// 显示绘制结果
		SDL_RenderPresent(m_sdl_window->m_renderer);

		return true;
	}*/
	


	//HWND ConsoleWindow = GetConsoleWindow();
	//if(ConsoleWindow) {
	//	ShowWindow(ConsoleWindow, SW_SHOW);
	//	EnableWindow(ConsoleWindow, true);
	//	SetWindowLongPtr(ConsoleWindow, GWLP_WNDPROC, (LONG_PTR)DefWindowProc);
	//}

	//if (PeekMessage(&msg, (HWND)m_窗口钩柄, 0, 0, PM_REMOVE)) {
	//	f_MakeForeground((HWND)m_窗口钩柄);
	//
	//	if (msg.message == WM_DESTROY || msg.message == WM_QUIT || msg.message == WM_CLOSE) 
	//		return false;
	//	if (msg.message == WM_SYSKEYUP) goto To_跳过系统按键;
	//	
	//	TranslateMessage(&msg);	
	//	DispatchMessage(&msg);	
	//
	//	goto To_跳过系统按键;
	//}
	//else 
	{
	To_跳过系统按键:
		assert(m_窗口GM->m_Root);
		if (!m_绘制) return true;
		
		
		static C_计时 窗口更新时间("UI窗口更新时间", 60);
		窗口更新时间.begin();

		
		m_Input->m_Key.lockKey[0] = GetKeyState(VK_CAPITAL) & 0x0001;
		f_input_取输入状态(m_Input);

		CANDIDATEFORM cand;
		cand.dwIndex = 0;
		cand.dwStyle = CFS_CANDIDATEPOS;
		POINT p;
		GetCursorPos(&p);
		ScreenToClient((HWND)m_窗口钩柄, &p);

		m_Input->m_鼠标全局坐标.x = p.x;
		m_Input->m_鼠标全局坐标.y = p.y;

		
		ivec2 m_ViewSize = { (int32)m_Size.x, (int32)m_Size.y };
		f_ui_筛选焦点组件(m_窗口GM, { float32(m_Input->m_鼠标全局坐标.x), float32(m_Input->m_鼠标全局坐标.y) });


		static C_计时 UI执行输入设备事计时("UI输入设备事计时", 60);
		UI执行输入设备事计时.begin();
		f_ui_执行输入设备事件(m_窗口GM, *m_Input);
		UI执行输入设备事计时.end();

		
		switch (S_光追后端::g_渲染状态) {
			case E_离线渲染状态::e_光追渲染_序列:
			case E_离线渲染状态::e_离线计算_序列:
				break;
			default:
				f_ui_绘制组件(m_窗口GM);

				static C_计时 UI布局计时("UI布局", 128);
				UI布局计时.begin();
				f_ui_更新UI布局(m_窗口GM, m_ViewSize);
				UI布局计时.end();
				
				static C_计时 UI属性更新计时("UI属性更新", 60);
				UI属性更新计时.begin();
				f_ui_更新UI部件属性(m_窗口GM, m_ViewSize);
				UI属性更新计时.end();


				f_bm_刷新缓存到GPU();
				f_ob_更新缓存列队();


				static C_计时 UI3D视口渲染计时("UI3D视口渲染计时", 60);
				UI3D视口渲染计时.begin();
				f_ui_3D视口绘制到屏幕();
				UI3D视口渲染计时.end();

				//界面绘制
				static C_计时 UI渲染计时("UI渲染", 60);
				UI渲染计时.begin();
				累计渲染 |= f_ui_渲染图层(m_窗口GM, m_ViewSize);
				UI渲染计时.end();

			
				//界面合成
				{
					static C_计时 UI合成计时("UI合成", 60);
					UI合成计时.begin();
					f_vg_begin(m_窗口GM);
					f_df_render_begin(m_窗口GM->m_渲染面, m_绘图环境);

					f_vg_set2DView(*m_Ctx, {{}, {m_Size.x, m_Size.y}}, nullptr);

					f_vg_tranform(m_ui合成画布, {0,0});
					f_vg_setComposition(*m_Ctx, *m_ui合成, 0, m_窗口GM->m_帧渲染层.size(), {{0,0}, {m_Size.x, m_Size.y}});
					f_vg_render(*m_窗口GM->m_UICtx, *m_ui合成画布, E_管线槽::e_UI合成);

					f_df_render_end(m_窗口GM->m_渲染面, m_绘图环境);
					UI合成计时.end();
				}


				f_ui_更新绑定数据(m_窗口GM);


		}

		窗口更新时间.end();
	}
	
	return m_显示;
	
}

void S_Window::f_显示(bool s) {
	if (s) {
		ShowWindow((HWND)m_窗口钩柄, SW_SHOW);
	}
	else {
		ShowWindow((HWND)m_窗口钩柄, SW_HIDE);
	}
	UpdateWindow((HWND)m_窗口钩柄);
	
	m_显示 = s;
}

void S_Window::f_创建绘制面(S_设备环境& ctx, ivec2 viewSize) {
	m_绘图框架 = ctx.m_绘图框架;
	HWND hWnd = (HWND)m_窗口钩柄;
	HDC hDC = GetDC((HWND)m_窗口钩柄); // NULL 表示获取屏幕的设备环境句柄

	// 取得屏幕的水平和垂直 PPI
	m_PDI.x = GetDeviceCaps(hDC, LOGPIXELSX);
	m_PDI.y = GetDeviceCaps(hDC, LOGPIXELSY);
	
	std::cout << "create Surface" << std::endl;
	m_采样 = ctx.m_采样数;
	m_Ctx = &ctx;
	//m_绘图框架->f_创建窗口绘制面(ctx, m_hInstance, hWnd, viewSize, m_采样);
	m_绘图环境 = ctx.m_绘图环境;

	std::cout << "create UI ctx" << std::endl;
	m_UIctx = new S_UI渲染环境(ctx, m_采样);
	m_UIctx->m_文字字号 = 12;
	m_UIctx->m_DPI = m_PDI.x / 96;


	m_窗口GM = f_create组件管理(*m_UIctx, _uVec2(viewSize));
	m_窗口GM->m_渲染面 = (S_WindowSurface*)f_df_win32Surface(ctx, m_hInstance, hWnd, viewSize, m_采样);
	m_窗口GM->m_Window = this;
	
	m_ui渲染画布 = f_surface_创建2D画布(0, ctx);
	m_ui合成画布 = f_surface_创建2D画布(0, ctx);
	m_ui合成 = f_vg_genComposition(ctx, *m_ui合成画布, E_图层混合模式::e_Normal);

	f_setSize(_Vec2(viewSize));
	m_裁剪大小 = {0, 0, float32(viewSize.x), float32(viewSize.y)};
	return;
	std::cout<<"load fonts"<<std::endl;
	std::string 字体文件 = f_sys_get字体文件目录().string() + "/msyh.ttc";
	//std::string 字体文件 = f_sys_get程序目录().string();
	f_ui加载字体(m_UIctx,
		{
			{
				{
					{0x0000, 0x007F}, {0x4E00, 0x9FA5},
					//{0x0000, 0xFFFF},
		            //0xFFFF,
				},

				"C:/Windows/Fonts/msyh.ttc",
				m_UIctx->m_文字字号,
				"雅黑"
			}
		}
	);
	
	f_ui加载字体(m_UIctx,
		{
			{
				{
					{0x0000, 0x007F}, {0x4E00, 0x9FA5},
					//{0x0000, 0xFFFF},
				},

				f_sys_get程序目录().string() + "/晴圆等宽.ttc",
				m_UIctx->m_文字字号,
				"晴圆等宽"
			}
		}
	);

}

void S_Window::f_创建绘制面(S_绘图框架* frame) {
	VkInstance instance = (VkInstance)f_df_getVK实例(frame);

	SDL_PropertiesID props = SDL_CreateProperties();

	m_sdl_window->m_MS = e_MS_1;
	if (!SDL_Vulkan_CreateSurface(m_sdl_window->m_window, instance, nullptr, &m_sdl_window->m_vk_surface)) {
		std::cerr << "Failed to create Vulkan surface for window." << std::endl;
	}
	f_df_windowSurface(frame->m_Ctx, (S_WindowSurface*)&m_sdl_window, _iVec2(m_Size));


	m_sdl_window->m_renderer = SDL_CreateRenderer(m_sdl_window->m_window, 0);
	//m_ui_sruface = f_surface_创建平面帧(frame->m_Ctx, _uVec2(m_Size));

	m_UIctx = new S_UI渲染环境(frame->m_Ctx, m_采样);
	m_窗口GM = f_create组件管理(*m_UIctx, {1024,576});
	m_UIctx->m_GM = m_窗口GM;
}


ivec2 S_Window::f_getSize() {
	return _iVec2(m_Size);
}

void S_Window::f_set标题(std::wstring 标题) {
	SetWindowText((HWND)m_窗口钩柄, 标题.c_str());
}

void S_Window::f_安装UI(C_Widget* ui) {
	f_ui_管理器添加根部件(m_窗口GM, ui);
	m_窗口GM->m_Root = ui;
	m_窗口GM->m_Root->m_UIctx = m_UIctx;


	RECT rctA;
	GetClientRect((HWND)m_窗口钩柄, &rctA);
	ivec2 viewSize = { rctA.right - rctA.left, rctA.bottom - rctA.top };
	f_ui_绘制组件(m_窗口GM);
	f_ui_组件布局(m_窗口GM, { float32(rctA.left), float32(rctA.top), float32(viewSize.x), float32(viewSize.y) });

	ui->m_父部件 = this;
}

void S_Window::f_清除UI() {
	m_窗口GM->m_根部件切换组.clear();
	m_窗口GM->m_Root = nullptr;
}





// 强制刷新系统输入法列表
void RefreshInputMethodList(HWND hwnd) {
	// 释放当前输入法上下文
	HIMC hImc = ImmGetContext(hwnd);
	if (hImc) {
		ImmReleaseContext(hwnd, hImc);
	}

	// 重新获取输入法上下文（触发系统重新加载输入法列表）
	hImc = ImmGetContext(hwnd);
	if (hImc) {
		ImmReleaseContext(hwnd, hImc);
	}

	// 发送 WM_INPUTLANGCHANGE 消息（可选）
	SendMessage(hwnd, WM_INPUTLANGCHANGE, (WPARAM)GetKeyboardLayout(0), 0);
}

// 激活并显示输入法
bool ActivateInputMethod(HWND hwnd) {
	// 获取当前输入法上下文
	HIMC hImc = ImmGetContext(hwnd);
	if (!hImc) {
		return false;
	}

	// 激活输入法
	ImmSetOpenStatus(hImc, TRUE);
	ImmAssociateContext(hwnd, hImc);
	// 释放输入法上下文
	ImmReleaseContext(hwnd, hImc);

	

	//PostMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, 0, 0);

	// 确保窗口有焦点
	SetFocus(hwnd);

	return true;
}



bool g字符输入 = true;

LRESULT CALLBACK Windows窗口回调(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	//std::cout<<"*************** hWnd = " << ( hWnd != GetConsoleWindow()) << " " << msg << "\n";
	
	S_Window* window;
	if (S_Engine::g_窗口容器.find((uint64)hWnd) == S_Engine::g_窗口容器.end()) {
		goto To_跳过事件;
	}
	else {
		window = S_Engine::g_窗口容器[(uint64)hWnd];
	}
	
	if ( IsWindowVisible(hWnd) == false || !window->m_窗口GM ) {
		goto To_跳过事件;
		return 0;
	}


	if (msg == WM_DESTROY || msg == WM_QUIT || msg == WM_CLOSE) {
		window->f_显示(false);
		return DefWindowProc(hWnd, msg, wParam, lParam);
		//PostQuitMessage(0);
	}

	
	
	switch (msg) {
		case WM_SETFOCUS:
		case WM_CREATE: {
			window->m_是否有焦点 = true;
			C_Widget::g_鼠标.abs = { float32(window->m_Input->m_鼠标全局坐标.x), float32(window->m_Input->m_鼠标全局坐标.y) };
			break;
		}

		case WM_SYSCOMMAND: {
			if (wParam == SC_CLOSE) {
				window->f_显示(false);
				return 0;
			}
			UINT uCmd = wParam & 0xFFF0;
			if (uCmd == SC_MINIMIZE) {
				//ShowWindow(hWnd, SW_HIDE);
			}
			else if (uCmd == SC_RESTORE) {
				ShowWindow(hWnd, SW_HIDE);
			}
			else {
				ShowWindow(hWnd, SW_SHOW);
			}

			goto To_跳过事件;
			break;
		}
			

		case WM_COMMAND: {
			int wmId = LOWORD(wParam);
			// 分析菜单选择:
			switch (wmId) {
				case IDM_EXIT:
					DestroyWindow(hWnd);
					break;
				default:
					return DefWindowProc(hWnd, msg, wParam, lParam);
			}
			break;
		}
		case MK_LBUTTON | MK_RBUTTON | MK_MBUTTON: {
			window->m_窗口GM->有输入事件 = true;
			break;
		}
		case WM_MOUSEMOVE: {
			window->m_Input->m_鼠标全局坐标.x = LOWORD(lParam); 
			window->m_Input->m_鼠标全局坐标.y = HIWORD(lParam); 
			window->m_窗口GM->有输入事件 = true;
			break;
		}

		case WM_KEYUP: {
			break;
		}
			
		case WM_KEYDOWN: {
			window->m_窗口GM->有输入事件 = true;
			bool 组合键输入 = (wParam < 48 || wParam >= 127);

			auto 顶层窗口数量 = f_widget_getTopNum(window->m_窗口GM);
			

			组合键输入 &= 顶层窗口数量 > 0 ? false : true;
			
			bool 文本按键 = false;

			文本按键 |= (TCHAR)wParam != '\b';
			文本按键 |= (TCHAR)wParam != '\t';
			文本按键 |= (TCHAR)wParam != '\r';
			文本按键 |= (TCHAR)wParam != '\n';
			
			文本按键 |= (TCHAR)wParam == 'C';
			文本按键 |= (TCHAR)wParam == 'V';
			文本按键 |= (TCHAR)wParam == 'X';

			组合键输入 |= 文本按键;

			
			if (window->m_窗口GM->m_当前文本输入框 && window->m_窗口GM->m_当前文本输入框->mf_按键字符输入 && 组合键输入) {
				g字符输入 = !window->m_窗口GM->m_当前文本输入框->mf_按键字符输入(window->m_窗口GM->m_当前文本输入框, (TCHAR)wParam, 组合键输入);
			}
			else {
				g字符输入 = true;
			}
			break;
		}
		case WM_CHAR: {
			bool 组合键输入 = (wParam >= 32 && wParam < 127);
			if (window->m_窗口GM->m_当前文本输入框 && window->m_窗口GM->m_当前文本输入框->mf_按键字符输入 && g字符输入 && 组合键输入) {
				TCHAR ch = (TCHAR)wParam;
				window->m_窗口GM->m_当前文本输入框->mf_按键字符输入(window->m_窗口GM->m_当前文本输入框, ch, false);
			}
			break;
		}

		case WM_MOVE: {
			RECT rctA;
			GetWindowRect((HWND)window->m_窗口钩柄, &rctA);
			window->m_窗口GM->窗口桌面位置.x = float32(rctA.left);
			window->m_窗口GM->窗口桌面位置.y = float32(rctA.top);
			break;
		}

		case WM_DPICHANGED: {
			UINT dpi = GetDpiForWindow(hWnd);
			window->m_UIctx->m_窗口DPI = dpi / 96.0f;
			window->m_UIctx->m_DPI = window->m_UIctx->m_窗口DPI;

			RECT rctA;
			GetWindowRect((HWND)window->m_窗口钩柄, &rctA);
			const vec4 area = { float32(rctA.left), float32(rctA.top), window->m_Size.x, window->m_Size.y };

			f_ui_组件布局(window->m_窗口GM, area);
			break;
		}

		
		case WM_SIZE: {
			
			ivec2 m_ViewSize = { LOWORD(lParam), HIWORD(lParam) };
			f_df_钳制视口大小(window->m_UIctx->m_Ctx, m_ViewSize);
			window->m_Size.x = m_ViewSize.x;
			window->m_Size.y = m_ViewSize.y;


			RECT rctA;
			GetWindowRect((HWND)window->m_窗口钩柄, &rctA);
			const vec4 area = { float32(rctA.left), float32(rctA.top), window->m_Size.x, window->m_Size.y };

			if (wParam == SIZE_MINIMIZED) {
				window->m_绘图框架->m_是否暂停 = true;
				window->m_绘制 = false;
			}
			else if (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED) {			//窗口最大化
				window->m_绘图框架->m_是否暂停 = false;
				window->m_绘制 = true;
				window->m_裁剪大小 = {0, 0, window->m_Size.x, window->m_Size.y};
				
				f_df_win32Surface_resize(window->m_UIctx->m_Ctx, window->m_窗口GM->m_渲染面, _uVec2(m_ViewSize));
				f_ui_组件布局(window->m_窗口GM, area);

				window->m_窗口GM->f_设置渲染层大小(_uVec2(m_ViewSize));
			}

			f = 0;
			break;
		}
		
		case WM_ACTIVATE: {
			if (LOWORD(wParam) == WA_INACTIVE) {
				window->m_处理输入事件 = false;
			}
			else {
				//重新连接输入设备
				window->m_处理输入事件 = true;
			}
			break;
		}
		
		
		case WM_IME_STARTCOMPOSITION: {
			//输入法进行
			HIMC hImc = ImmGetContext(hWnd);
			//f_widget_set当前正在输入的文本(L"输入法");
			//HKL currentLayout = GetKeyboardLayout(0);
			//std::cout << "currentLayout" << currentLayout << std::endl;
			f_win32_set输入法面板位置(hImc);

			ImmReleaseContext(hWnd, hImc);
			break;
		}
		//获取输入法字符
		case WM_IME_COMPOSITION: {
			auto hImc = ImmGetContext(hWnd);
			
			auto txt = f_win32_get输入法输入字符(hImc);
			if (txt.size()) {
				std::wcout << "WM_IME_COMPOSITION 输入法 " << f_str_u16_to_wstring(txt) << endl;
				if (window->m_窗口GM->m_当前文本输入框 && window->m_窗口GM->m_当前文本输入框->mf_行文本输入) {
					window->m_窗口GM->m_当前文本输入框->mf_行文本输入(window->m_窗口GM->m_当前文本输入框, txt, E_字符输入类型::e_输入法字符);
				}
				f_win32_set输入法面板位置(hImc);
			}

			//输入结束
			if (lParam & GCS_CURSORPOS) {
				std::cout << "完成输入 " << WM_IME_COMPOSITION << std::endl;
			}
			
			ImmReleaseContext(hWnd, hImc);
			std::cout<<"hWnd = " << (hWnd == GetConsoleWindow()) << " " << wParam << " " << lParam << "\n";
			break;
		}
		//输入法完成
		case WM_IME_ENDCOMPOSITION: {
			HIMC hImc = ImmGetContext(hWnd);
			auto txt = f_win32_get输入法完成文本(hImc);

			if (txt.size()) {
				std::wcout << "WM_IME_COMPOSITION 输入法 " << hWnd << " = " << f_str_u16_to_wstring(txt) << endl;
				if (window->m_窗口GM->m_当前文本输入框 && window->m_窗口GM->m_当前文本输入框->mf_行文本输入) {
					window->m_窗口GM->m_当前文本输入框->mf_行文本输入(window->m_窗口GM->m_当前文本输入框, txt, E_字符输入类型::e_输入法组合);
				}
			}


			ImmReleaseContext(hWnd, hImc);
			//f_widget_结束输入法();
			//std::wcout << "WM_IME_ENDCOMPOSITION 输入法取消 " << f_str_u16_to_wstring(txt) << endl;
			
			break;
		}
		
		//case WM_INPUTLANGCHANGE:
		//case WM_INPUTLANGCHANGEREQUEST: {
		//	// 输入法切换事件
		//	// 获取当前激活的输入法
		//	//HKL hkl = (HKL)lParam;
		//	//ActivateKeyboardLayout(hkl, KLF_REPLACELANG);
		//	//SendMessage(hWnd, WM_IME_CONTROL, IMC_SHOWCANDIDATE, 0);
		//
		//	// 更新UI显示
		//	//wchar_t imeName[256] = {0};
		//	//ImmGetDescription((HKL)wParam, imeName, 256);
		//	//SetWindowText(hWnd, imeName);
		//	//ActivateInputMethod(hWnd);
		//
		//	//DWORD tid = GetWindowThreadProcessId(hWnd, nullptr);
		//	//HKL currentLayout = GetKeyboardLayout(tid);
		//	//ActivateKeyboardLayout((HKL)(tid + 1), 0);
		//
		//	//HKL hkl = LoadKeyboardLayout(_T("00000804"), KLF_ACTIVATE);
		//	//SendMessage(hWnd, WM_INPUTLANGCHANGEREQUEST, 0, 0); 
		//	
		//	// 处理输入法切换
		//	std::cout << "切换到输入法" << std::endl;
		//	goto To_跳过事件;
		//	break;
		//}
		
		case WM_ENTERSIZEMOVE:
			window->m_绘图框架->m_是否暂停 = true;
			return 0;

		case WM_EXITSIZEMOVE:			
			window->m_绘图框架->m_是否暂停 = false;
			return 0;
		
		case WM_GETMINMAXINFO:
			((MINMAXINFO*)lParam)->ptMinTrackSize.x = 200;
			((MINMAXINFO*)lParam)->ptMinTrackSize.y = 200;
			goto To_跳过事件;
			return 0;

		case WM_SYSCHAR:
		case WM_SYSDEADCHAR:
			break;

		case WM_SETCURSOR: {
			if (f_window_set鼠标样式(C_Widget::g_鼠标样式) == false) {
				return DefWindowProc(hWnd, msg, wParam, lParam);
			}
			break;
		}
		

		case WM_DROPFILES: {
			HDROP hdrop = (HDROP)wParam;
			wchar_t sDropFilePath[MAX_PATH + 1];

			//获取
			int32 拖放文件个数数量 = 0;
			拖放文件个数数量 = DragQueryFile(hdrop, 0xFFFFFFFF, NULL, 0);
			for (int i = 0; i < 拖放文件个数数量; i++) {
				DragQueryFile(hdrop, i, sDropFilePath, sizeof(sDropFilePath));
				std::wstring 路径 = sDropFilePath;

				C_Widget管理::m_拖放文件名.push_back(f_str_wstring_to_u16(路径));
			}
			DragFinish(hdrop);

			GetCursorPos((POINT*)&window->m_Input->m_鼠标全局坐标);
			ScreenToClient((HWND)window->m_窗口钩柄, (POINT*)&window->m_Input->m_鼠标全局坐标);
			C_Widget::g_鼠标.gPos = { float32(window->m_Input->m_鼠标全局坐标.x), float32(window->m_Input->m_鼠标全局坐标.y) };
			f_ui_文件拖入(window->m_窗口GM, C_Widget::g_鼠标.gPos);
			break;
		}


		//============== 焦点 ===============
		case WM_KILLFOCUS:
			window->m_是否有焦点 = false;
			break;

		//case WM_WINDOWPOSCHANGING :
		//	break;
		default:
			To_跳过事件:
			return DefWindowProc(hWnd, msg, wParam, lParam);
	}

	return 0;
}



HKL currentHKL = NULL;                  // 当前输入法布局
HHOOK hMsgHook = NULL;                  // 消息钩子

// 消息钩子过程
LRESULT CALLBACK f_转发终端窗口消息(int nCode, WPARAM wParam, LPARAM lParam) {
	if (nCode >= 0) {
		MSG* pMsg = (MSG*)lParam;

		// 捕获输入法切换事件
		if (pMsg->message == WM_INPUTLANGCHANGE) {
			currentHKL = (HKL)pMsg->wParam;

			// 将输入法变更同步到所有有焦点的子窗口
			for (auto& window : S_Engine::g_窗口容器) {
				
				SendMessage((HWND)window.first, WM_INPUTLANGCHANGE, (WPARAM)currentHKL, 0);


			}
		}
	}
	return CallNextHookEx(hMsgHook, nCode, wParam, lParam);
}

// 初始化 SDL3 窗口和渲染器
bool f_window_Init() {
	//static auto err = SDL_Init(SDL_INIT_VIDEO);
	//if (err) {
	//	return true;
	//} 

	//hMsgHook = SetWindowsHookEx(WH_GETMESSAGE, f_转发终端窗口消息, NULL, GetCurrentThreadId());
	// 初始化当前输入法
	//currentHKL = GetKeyboardLayout(0);

	//HWND consoleHwnd = GetConsoleWindow();
	//if (consoleHwnd) {
	//	HIMC hIMC = ImmGetContext(consoleHwnd);
	//	if (hIMC) {
	//		ImmSetOpenStatus(hIMC, FALSE); // 关闭输入法
	//		ImmReleaseContext(consoleHwnd, hIMC);
	//	}
	//}

	//HWND consoleHwnd = GetConsoleWindow();
	//if (consoleHwnd) {
	//	// 获取并“锁定”输入法上下文
	//	HIMC hIMC = ImmGetContext(consoleHwnd);
	//	if (hIMC) {
	//		// 强制开启输入法（避免临时关闭导致的状态问题）
	//		ImmSetOpenStatus(hIMC, TRUE);
	//		// 设置为默认上下文，减少切换失效概率
	//		ImmAssociateContext(consoleHwnd, hIMC);
	//		//ImmReleaseContext(consoleHwnd, hIMC);
	//	}
	//}

	return false;
}

void f_window_创建SDL窗口(S_Window* window, std::string 标题, vec2 size) {
	window->m_sdl_window->m_window = SDL_CreateWindow(标题.c_str(), size.x, size.y
													  , SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY);
	//SDL_Vulkan_CreateSurface(window->m_sdl_window);
	window->m_采样 = E_MS次数::e_MS_1;
	window->m_Size = size;
}





/*



static vec2 viewOffset[32] = {
{0,0},
{0,1},
{1,0},
{0,-1},
{-1,0},
{0.707107,	0.707107},
{0.707107,	-0.707107},
{-0.707107,	-0.707107},
{-0.707107,	0.707107},

{0,2},
{1,1.7321},
{1.7321,1},
{2,0},
{1.7321,-1},
{1,-1.7321},
{0,-2},
{-1,-1.7321},
{-1.7321,-1},
{-2,0},
{-1.7321,1},
{-1,1.7321},
};
static float32 viewSizeOffset[32] = {
0,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,

0.35,
0.35,
0.35,
0.35,
0.35,
0.35,
0.35,
0.35,
0.35,
0.35,
0.35,
0.35,
};

*/